package com.qd.panda.service;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.cdqidi.core.weixinmanager.domain.MiddleUserDTO;
import com.cdqidi.core.weixinmanager.model.MiddleUser;
import com.cdqidi.core.weixinmanager.service.MiddleUserService;
import com.cdqidi.util.DateUtil;
import com.cdqidi.util.RedisTemplateUtil;
import com.qd.common.panda.config.PandaParkConfigDTO;
import com.qd.common.panda.constant.PandaConstant;
import com.qd.common.panda.domain.entity.integral.UserIntegralDetailDTO;
import com.qd.common.panda.domain.entity.msg.UserMsgDTO;
import com.qd.panda.model.ChannelUser;
import com.qd.panda.model.CommodityStatistics;
import com.qd.panda.model.UserIntegralDetail;
import com.qd.panda.model.UserStroke;
import com.qd.panda.service.card.CardPlanHolderService;
import com.qd.panda.service.commodity.CommodityStatisticsService;
import com.qd.panda.service.func.ChannelScanLogService;
import com.qd.panda.service.func.ChannelUserService;
import com.qd.panda.service.integral.UserIntegralDetailService;
import com.qd.panda.service.integral.UserIntegralService;
import com.qd.panda.service.msg.UserMsgService;
import com.qd.panda.service.park.CarParkService;
import com.qd.panda.service.stroke.order.GasOrderService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * @author sjk
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class AsyncService {

    private final UserIntegralService userIntegralService;
    private final UserIntegralDetailService userIntegralDetailService;
    private final CarParkService carParkService;

    private final UserMsgService userMsgService;
    private final StringRedisTemplate stringRedisTemplate;
    private final CardPlanHolderService cardPlanHolderService;

    private final CommodityStatisticsService commodityStatisticsService;

    private final ChannelUserService channelUserService;
    private final ChannelScanLogService channelScanLogService;

    private final PandaParkConfigDTO parkConfig;
    @Resource
    private MiddleUserService middleUserService;

    /**
     * 生成积分
     *
     * @param userId    用户ID
     * @param integral  积分
     * @param note      备注
     * @param pointType 积分类型
     * @param bid       业务ID
     */
    @Async

    public void createIntegral(String userId, BigDecimal integral, String note, String pointType, String bid) {
        if (null == integral) {
            integral = BigDecimal.valueOf(RandomUtil.randomDouble(10, 20));
        }
        userIntegralService.saveIntegral(userId, integral, note, pointType, 1, bid);
    }

    /**
     * 删除积分
     *
     * @param bid 业务ID
     */
    @Async
    public void deleteIntegral(String bid) {
        //查询出已经生成的积分，如果没有说明已经删除了或者用户没有使用积分，那么就不处理
        UserIntegralDetailDTO query = new UserIntegralDetailDTO();
        query.setBid(bid);
        List<UserIntegralDetail> list = userIntegralDetailService.getList(query);
        if (!list.isEmpty()) {
            list.forEach(userIntegralDetail -> userIntegralService.deleteIntegral(userIntegralDetail.getDid()));
        }
    }

    /**
     * 添加预约超时通知消息(只有超时取消的才会发送消息通知)
     *
     * @param userStroke 业务ID,用户ID,停车场ID
     * @param now        当前时间
     */
    @Async
    @Transactional(rollbackFor = Exception.class)
    public void createNoticeMsg(UserStroke userStroke, LocalDateTime now) {
        String bid = userStroke.getSid();
        String userId = userStroke.getUserId();
        String parkId = userStroke.getParkId();
        final String parkName = carParkService.idToDisplay(parkId);
        if (!StringUtils.hasLength(parkName)) {
            log.info("parkName:{},parkId: {}", parkName, parkId);
            return;
        }
        String stringBuilder = "您" + "\"" + parkName + "\"的优惠停车行程已于" +
                DateUtil.localDateTimeToStr(now) + "到期," +
                "请重新下单";
        UserMsgDTO userMsgDTO = new UserMsgDTO();
        userMsgDTO.setUserId(userId);
        userMsgDTO.setMsgType(PandaConstant.MSG_TYPE_1);
        userMsgDTO.setNote(stringBuilder);
        userMsgDTO.setBid(bid);
        userMsgDTO.setCanRead(0);
        userMsgDTO.setAddTime(now);
        userMsgService.save(userMsgDTO);
        userMsgDTO.freeData();
    }

    /**
     * 更新卡状态为未使用
     *
     * @param orderId 订单ID
     */
    @Async
    @Transactional(rollbackFor = Exception.class)
    public void updateCard(String orderId) {
        String cardId = stringRedisTemplate.opsForValue().get(RedisTemplateUtil.getRedisCacheKey(GasOrderService.ORDER_ID_TO_CARD_ID, orderId));
        if (StringUtils.hasLength(cardId)) {
            cardPlanHolderService.updateUseCard(cardId, orderId, PandaConstant.USE_STATE_1);
        }
    }

    /**
     * 第三方回调，说明该优惠券已经使用
     *
     * @param thirdCouponCode 第三方优惠券ID
     */
    @Async
    public void couponUsed(String thirdCouponCode) {
        cardPlanHolderService.couponUsed(thirdCouponCode, LocalDateTime.now());
    }

    @Async
    @Transactional(rollbackFor = Exception.class)
    public void saveCommodityStatistics(CommodityStatistics model) {
        commodityStatisticsService.save(model);
        model.freeData();
    }

    /**
     * 自动绑定微信小程序
     *
     * @param unionId 微信公众号unionId
     */
    @Async
    @Transactional(rollbackFor = Exception.class)
    public void createWxUser(String openid, String unionId) {
        List<MiddleUser> list = middleUserService.getListByUnionId(unionId);
        if (list.isEmpty()) {
            return;
        }
        MiddleUser wxaMiddleUser = list.stream().filter(user -> user.getAppId().equals(parkConfig.getDefaultMiniProgramAppId())).findFirst().orElse(null);

        if (null == wxaMiddleUser) {
            MiddleUser middleUser = list.stream().filter(user -> user.getAppId().equals(parkConfig.getDefaultAppId())).findFirst().orElse(null);
            if (null == middleUser) {
                return;
            }
            log.info("自动绑定微信小程序,openid: {},unionId: {}", openid, unionId);
            MiddleUserDTO middleUserDTO = new MiddleUserDTO();
            middleUserDTO.setRId(IdWorker.getIdStr());
            middleUserDTO.setAppId(parkConfig.getDefaultMiniProgramAppId());
            middleUserDTO.setMobile(middleUser.getMobile());
            middleUserDTO.setBindTime(LocalDateTime.now());
            middleUserDTO.setOpenid(openid);
            middleUserDTO.setUnionId(unionId);
            middleUserDTO.setUserId(middleUser.getUserId());
            middleUserService.save(middleUserDTO);
            middleUserDTO.freeData();
            middleUser.freeData();
        } else {
            wxaMiddleUser.freeData();
        }
        list.clear();
    }

    /**
     * 创建渠道发展用户
     * @param channelUser 渠道用户
     */
    @Async
    @Transactional(rollbackFor = Exception.class)
    public void createChannelUser(ChannelUser channelUser) {
        channelUserService.bind(channelUser);
        channelUser.freeData();
    }

    @Async
    @Transactional(rollbackFor = Exception.class)
    public void unbindChannelUser(String userId) {
        channelUserService.unbind(userId);
    }

    @Async
    @Transactional(rollbackFor = Exception.class)
    public void addChannelScanLog(String funcId,String ipAddress,LocalDateTime now,String userId,String mobile){
        channelScanLogService.addLog(funcId,ipAddress,now,userId,mobile);
    }
}